package self.zhangkang.chart.view.kline.main

import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import self.zhangkang.chart.data.KLineInfo
import self.zhangkang.chart.tools.CanvasTools
import self.zhangkang.chart.tools.NumberFormatUtils
import self.zhangkang.chart.view.IndexLineInfo
import self.zhangkang.chart.view.IndexNameConfig
import self.zhangkang.chart.view.kline.KLineIndex
import self.zhangkang.chart.view.kline.KLineViewColor
import self.zhangkang.chart.view.kline.KLineViewDimen
import self.zhangkang.chart.view.pool.PathPool
import self.zhangkang.chart.view.pool.RectPool

/**
 * @author : Android-张康
 * created on: 2023/5/9 18:19
 * description:
 */
internal class KLineBOLL(
    private val pathPool: PathPool,
    private val rectPool: RectPool,
    private val kLineViewColor: KLineViewColor,
    private val kLineViewDimen: KLineViewDimen,
    indexNameConfig: IndexNameConfig
) : BaseMainKLine(pathPool, rectPool, kLineViewColor, kLineViewDimen, indexNameConfig) {

    private val upperLineInfo = object : IndexLineInfo {
        override fun getName(): String {
            return "UPPER"
        }

        override fun getLineColor(): Int {
            return kLineViewColor.bollUpperColor
        }

        override fun getIndexValue(kLineInfo: KLineInfo): Float {
            return kLineInfo.boll.up
        }
    }

    private val bollLineInfo = object : IndexLineInfo {

        override fun getName(): String {
            return "BOLL"
        }

        override fun getLineColor(): Int {
            return kLineViewColor.bollBollColor
        }

        override fun getIndexValue(kLineInfo: KLineInfo): Float {
            return kLineInfo.boll.mid
        }
    }

    private val lowerLineInfo = object : IndexLineInfo {

        override fun getName(): String {
            return "LOWER"
        }

        override fun getLineColor(): Int {
            return kLineViewColor.bollLowerColor
        }

        override fun getIndexValue(kLineInfo: KLineInfo): Float {
            return kLineInfo.boll.down
        }
    }

    private val indexLineInfoList = mutableListOf(
        upperLineInfo,
        bollLineInfo,
        lowerLineInfo,
    )

    private val indexLineInfoPath = mutableMapOf<IndexLineInfo, Path>()

    /**
     * 获取指标类型
     */
    override fun getIndexInfo(): KLineIndex {
        return KLineIndex.BOLL
    }

    /**
     * 计算最大值
     *
     * @param kLineInfo 当前值
     */
    override fun calculationMaxAndMin(kLineInfo: KLineInfo) {
        super.calculationMaxAndMin(kLineInfo)
        var maxValue = getMaxValue()
        var minValue = getMinValue()
        indexLineInfoList.forEach {
            val indexValue = it.getIndexValue(kLineInfo)
            if (indexValue.isFinite()) {
                maxValue = maxOf(maxValue, indexValue)
                minValue = minOf(minValue, indexValue)
            }
        }
        setMaxAndMinValue(maxValue, minValue)
    }

    /**
     * 绘制当前值
     *
     * @param canvas 画布
     * @param startX 开始的 X
     * @param startY 开的的 Y
     * @param stopX 结束的 X
     * @param stopY 结束的 Y
     * @param linePaint 线的画笔
     * @param textPaint 文字的画笔
     * @param marginTop 距离顶部的距离
     * @param span
     * @param indexValueHorizontalSpace 指标值之间的横向距离
     * @param indexValueVerticalSpace 指标值之间的纵向距离
     * @param kLineInfo 当前的值
     * @param kLineIsLine K线是否为一条线
     *
     * @return 绘制结束 X 坐标
     */
    override fun drawMainCurrentIndexInfo(
        canvas: Canvas,
        startX: Float,
        startY: Float,
        stopX: Float,
        stopY: Float,
        linePaint: Paint,
        textPaint: Paint,
        marginTop: Float,
        span: Int,
        indexValueHorizontalSpace: Float,
        indexValueVerticalSpace: Float,
        kLineInfo: KLineInfo,
        kLineIsLine: Boolean
    ): Float {
        //先绘制指标名称
        val indicatorNameWidth = super.drawMainCurrentIndexInfo(
            canvas,
            startX,
            startY,
            stopX,
            stopY,
            linePaint,
            textPaint,
            marginTop,
            span,
            indexValueHorizontalSpace,
            indexValueVerticalSpace,
            kLineInfo,
            kLineIsLine
        )
        textPaint.textSize = kLineViewDimen.indexValueTextSize
        var indicatorStart = startX + indicatorNameWidth + indexValueHorizontalSpace
        var drawTextInVerticalCenter: Int
        indexLineInfoList.forEach { maInfo ->
            val indexValue = maInfo.getIndexValue(kLineInfo)
            val currentString = buildString {
                append(maInfo.getName())
                append(":")
                if (indexValue.isFinite()) {
                    append(NumberFormatUtils.priceNumberFormat(indexValue))
                } else {
                    append("--")
                }
            }
            textPaint.color = maInfo.getLineColor()
            drawTextInVerticalCenter = CanvasTools.drawTextInVerticalCenter(
                canvas, indicatorStart, startY, stopY, currentString, textPaint, rectPool = rectPool
            )
            indicatorStart += drawTextInVerticalCenter + indexValueHorizontalSpace
            if (!kLineIsLine) {
                val indexPath = pathPool.acquire()
                indexLineInfoPath[maInfo] = indexPath
            }
        }
        return indicatorStart
    }

    /**
     * 绘制当前值内容
     *
     * @param canvas 画布
     * @param startX 开始的 X
     * @param startY 开的的 Y
     * @param stopX 结束的 X
     * @param stopY 结束的 Y
     * @param textPaint 文字的画笔
     * @param linePaint 线的画笔
     * @param kLineInfo 当前的值
     * @param isFirst 是否为第一次
     * @param yangLineIsFill 阳线是否实心
     * @param totalTranslateX X轴总的位移
     * @param candlestickWidth 蜡烛的宽度
     * @param halfCandlestickWidth 蜡烛的一半宽度
     * @param kLineIsLine K线是否为一条线
     */
    override fun drawItemContent(
        canvas: Canvas,
        startX: Float,
        startY: Float,
        stopX: Float,
        stopY: Float,
        textPaint: Paint,
        linePaint: Paint,
        kLineInfo: KLineInfo,
        isFirst: Boolean,
        yangLineIsFill: Boolean,
        totalTranslateX: Float,
        candlestickWidth: Float,
        halfCandlestickWidth: Float,
        kLineIsLine: Boolean
    ) {
        super.drawItemContent(
            canvas,
            startX,
            startY,
            stopX,
            stopY,
            textPaint,
            linePaint,
            kLineInfo,
            isFirst,
            yangLineIsFill,
            totalTranslateX,
            candlestickWidth,
            halfCandlestickWidth,
            kLineIsLine
        )
        //Path 的横坐标
        var pathX = halfCandlestickWidth + totalTranslateX
        if (pathX < 0) {
            pathX = halfCandlestickWidth
        }
        indexLineInfoPath.forEach {
            val indexValue = it.key.getIndexValue(kLineInfo)
            val indexY = getPriceRangeItem() * (getMaxValue() - indexValue) + startY
            val path = it.value
            if (isFirst) {
                if (indexY <= stopY) {
                    path.moveTo(pathX, indexY)
                } else {
                    path.moveTo(pathX, stopY)
                }
            } else {
                if (indexY <= stopY) {
                    path.lineTo(pathX, indexY)
                }
            }
        }
    }

    /**
     * 绘制完整个当前内容之后
     *
     * @param canvas 画布
     * @param paint 画笔
     */
    override fun afterDrawItemContent(canvas: Canvas, paint: Paint) {
        super.afterDrawItemContent(canvas, paint)
        paint.strokeWidth = kLineViewDimen.indexLineStrokeWidth
        indexLineInfoPath.forEach {
            val maColor = it.key.getLineColor()
            val maPath = it.value
            paint.color = maColor
            canvas.drawPath(maPath, paint)
            pathPool.release(maPath)
        }
        indexLineInfoPath.clear()
    }

}